/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2013 Jean-Sebastien Lerat (Jean-Sebastien.Lerat@ulb.ac.be)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
 *
 * @author Jean-Sebastien Lerat (Jean-Sebastien.Lerat@ulb.ac.be)
 * @version 1.00, 24/06/2013
 * Native implementation of the measure library for CoNet (http://psbweb05.psb.ugent.be/conet/)
 */

#ifndef __MEASURES_H__
	#define __MEASURES_H__

#include "jniutils.h"
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define ERROR_VALUE NAN
#define EULER_MASCHERONI 0.57721566490153286060651209008240243104215933593992
#define EPSILON	1E-10
//log(2.0)
#define LOG_E_2	0.6931471805599453
#define GAUSSIAN_KERNEL(mult,xi,xj) exp(mult * (xi * xi + xj * xj))

#define equals(a,b) (!strcmp(a,b))

//underflow (Numerical Analysis course) ( exp(0.5*log(x)) <=> sqrt(x) )
#define ssqrt(x) (x!=0.0?exp(0.5*log(x)):0.0)
#define slog(x) (x!=0.0?log(x):0.0)

typedef jdouble (*Measure)(const void*,const jdouble*,const jdouble*,const jboolean *,const jsize);
typedef jdouble (*Entropy)(const void* config,double *,const jsize,const int,const int);


typedef struct MeasureFunction{
	Measure function;
	void* config;
} MeasureFunction;

int mergesortCounting(const jboolean * ,int * toSort,jdouble * ,const jsize len);
void bubbleSort(jdouble *,jdouble *,const jsize);
void bubbleSortPositional(jdouble *,int *,const jsize);
int countSwap(jdouble * comparable,const jsize len);
int naturalRank(const jboolean * ,const jdouble *,jdouble *,int * ,const jsize);
jdouble fastSum(const jdouble* vector,const jboolean *,jsize);
jdouble fastMean(const jdouble* vector,const jboolean *,jsize);
double digamma(double);
long countOccurenciesMat(const jdouble**,const jsize,double *,const jsize,int *,const jboolean *);
long countOccurenciesVect(const jdouble*,const jsize,double *,const jsize,int *,const jboolean);

jdouble pearson(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble spearman(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble kullback_leibler(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble bray_curtis(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble mutual_information(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble kendall(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble euclidean(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble hellinger(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble chi_square(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble variance_log_ratios(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble distance_correlation(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble polynomial_regression(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble hilbert_schmidt(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble mic(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble jensen_shannon(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble empirical_entropy(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble shannon_entropy(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble steinhaus(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);
jdouble sg_entropy(const void* config,const jdouble*,const jdouble*,const jboolean *,const jsize);

double entropy_sg(const void* config,double *,const jsize,const int,const int);
double entropy_shannon(const void* config,double *,const jsize,const int,const int);
double entropy_empirical(const void* config,double *,const jsize,const int,const int);



MeasureFunction defineMeasure(JNIEnv * env,jobject config);

#endif
